package com.jiangruan.javaproject.request;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import java.util.Set;

/**
 * @author:huayuzhuo
 * @email:2798866329@qq.com
 * @desc:  该类用于封装提供网络请求的功能代码，发起网络请求并返回数据
 * @datatime: 2021/12/14 22:03
 */
public class HttpUtils {

    //迭代器是查看个数的，一般集合与数据库查询的时候使用
        //因为请求的url都不一样，所以这里传入参数
    public static String get(String path){

        InputStream inputStream = null;                 //声明输入流对象
        InputStreamReader inputStreamReader = null;     //声明转换流对象
        BufferedReader reader = null;               //声明缓冲字符流对象
        String line = "";                       //该变量用于存储字符流读取一行内容，这里表示最开始空行
        String result = "";                         //每次读取到数据以后都要追加的读取结果

        //语句抛错，一般使用try抛错
        try {                               //java发起网络请求需要实例URL对象
            URL url = new URL(path);
            //Union Resource Location   统一资源定位
            URLConnection connection = url.openConnection();   //这里会返回一个URLConnection类型的数据
                //这里方法类似go里的do方法，用于发起请求，进行连接
            connection.connect();

            //输入流
            inputStream = connection.getInputStream();
            //为了可以使用字符流，这里将stream转换read,满足缓冲字符流的方法参数条件
            inputStreamReader = new InputStreamReader(inputStream);
            //这里输入流接收数据可以使用字符流，它是按行读再转换为字符串，字节流则是一个字节一个字节读
            reader = new BufferedReader(inputStreamReader);

            //为了简洁一些，这里可以直接合在一起
            //reader = new BufferedReader(new InputStreamReader(inputStream));
            //由于reader.readLine()只读一行，所以这里采用while循环读
            //reader.readLine();

            while ((line = reader.readLine()) != null){
                result += line;
            }


        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //按照先开后关的规则，关闭资源流 由于关闭资源时要抛错，所以这里使用try包裹关闭语句
                try {
                    if (reader != null) {
                        reader.close();
                    }
                    if (inputStreamReader != null){
                        inputStreamReader.close();
                    }
                    if (inputStream != null){
                        inputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
        //最后返回读取到的数据追加结果集
        return result;
    }

    /**
     * 封装的用java实现的原生post请求
     * @param path  请求的路径
     * @param header  请求头信息
     * @param data  请求数据
     * @return   请求的响应数据
     */
                                            //这里设一个集合传设置请求头的属性以及一个要发送的数据
    public static String post(String path, Map<String,String> header,byte[] data){

        OutputStream outputStream = null;           //声明发送请求对象
        BufferedReader reader = null;               //声明缓冲字符流对象
        String result = "";     //最终要返回的数据

        try {
            URL url = new URL(path);
            //获得连接对象，再强制转换连接对象类型为HttpURLConnection
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            //设置连接对象允许发送数据和接收数据以及请求类型
            connection.setDoOutput(true);
            connection.setDoOutput(true);
            connection.setRequestMethod("POST");

            //设置请求头属性   ContentType:application/json    Authorization:"Basic "+base64(用户信息)
            //但是一些请求不需要设置请求头设置，所以这里判断装请求头属性的形参集合header有没有数据
            if (!header.isEmpty()){     //集合不为空,则设置请求头
                //不使用for或迭代器遍历，这里拿到集合中所有key就能导value
                //拿到map中所有key，再装入set集合
                Set<String> keys = header.keySet();
                //问题变成遍历set集合
                for (String key : keys) {           //获得迭代的key
                    String value = header.get(key);     //获得key对应的value值
                    connection.setRequestProperty(key,value);
                }
            }

            connection.connect();

            //把请求数据发送到请求的服务端
            outputStream = connection.getOutputStream();
            outputStream.write(data);   //写入发送数据
            outputStream.flush();       //刷的意思

            //等待接送的数据   这里仍然采用缓冲字符流按行读，速度更快  所以new一个转换流将字节流转换成字符流
            reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null){
                result += line;
            }


        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭资源流
            try {
                if (reader != null) {
                    reader.close();
                }
                if (outputStream != null){
                    outputStream.close();
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }

        return result;
    }



}
